#include "clib_bsd_socket.h"
#include "clib_stack.h"

i32_t 
clib_bsd_getsockopt(i32_t sockid,
                i32_t level,
                i32_t optname,
                void *optval,
                socklen_t *optlen) 
{
    // if(sockid < 0 || sockid >= l4_satck.sock_n) {
    //     return -1;
    // }
    
    clib_sock_t* sock = clib_get_sock_by_id(&l4_satck, sockid);

    return clib_getsockopt(sock, sockid, level, optname, optval, optlen);
}

i32_t 
clib_bsd_setsockopt(i32_t sockid,
                i32_t level,
		        i32_t optname,
                const void *optval,
                socklen_t optlen)
{
    clib_sock_t* sock = clib_get_sock_by_id(&l4_satck, sockid);

    return clib_setsockopt(sock, sockid, level, optname, optval, optlen);
}

i32_t 
clib_bsd_setsock_nonblock(i32_t sockid) 
{
    clib_sock_t* sock = &l4_satck.sock_table[sockid];

    return clib_setsock_nonblock(sock, sockid);
}

/* mtcp_socket_ioctl: similar to ioctl, 
   but only FIONREAD is supported currently */
i32_t 
clib_bsd_socket_ioctl(i32_t sockid, i32_t request, void *argp) 
{
    clib_sock_t* sock = clib_get_sock_by_id(&l4_satck, sockid);

    return clib_socket_ioctl(sock, sockid, request, argp);
}

i32_t 
clib_bsd_socket(i32_t domain, i32_t type, i32_t protocol)
{
    i32_t idx;
    stack_ctx_t *ctx;

    idx = clib_stack_index_get();
    if(idx < 0 || idx >= l4_satck.ctx_n) {
        return -1;
    }
    ctx = l4_satck.ctx[idx];

    // TODO 获取socket
    // domain:地址族,通常为AF_INET(IPv4)或AF_INET6(IPv6)。
    // type:套接字类型,可以是SOCK_STREAM(TCP)或SOCK_DGRAM(UDP)。
    // protocol:协议,通常为0,表示自动选择合适的协议。

    return -1;
}

i32_t 
clib_bsd_bind(i32_t sockid, 
		  const struct sockaddr *addr,
          socklen_t addrlen)
{
    clib_sock_t* sock = &l4_satck.sock_table[sockid];

    return clib_bind(sock, sockid, addr, addrlen);
}


i32_t 
clib_bsd_listen(i32_t sockid, i32_t backlog) 
{
    clib_sock_t* sock = &l4_satck.sock_table[sockid];

    return clib_listen(sock, sockid, backlog);
}

i32_t 
clib_bsd_accept(i32_t sockid, struct sockaddr *addr, socklen_t *addrlen)
{
    clib_sock_t* sock = &l4_satck.sock_table[sockid];

    return clib_accept(sock, sockid, addr, addrlen);
}

// i32_t 
// clib_init_rss(mctx_t mctx, in_addr_t saddr_base, i32_t num_addr, 
// 		in_addr_t daddr, in_addr_t dport);

i32_t 
clib_bsd_connect(i32_t sockid, 
		     const struct sockaddr *addr,
             socklen_t addrlen) 
{
    clib_sock_t* sock = clib_get_sock_by_id(&l4_satck, sockid);

    return clib_connect(sock, sockid, addr, addrlen);
}

i32_t 
clib_bsd_close(i32_t sockid) 
{
    clib_sock_t* sock = clib_get_sock_by_id(&l4_satck, sockid);

    return clib_close(sock, sockid);
}

i32_t
clib_bsd_getsockname(i32_t sockid,
                 struct sockaddr *addr,
                 socklen_t *addrlen)
{
    clib_sock_t* sock = clib_get_sock_by_id(&l4_satck, sockid);

    return clib_getsockname(sock, sockid, addr, addrlen);
}

i32_t
clib_bsd_getpeername(i32_t sockid,
                 struct sockaddr *addr,
		         socklen_t *addrlen)
{
    clib_sock_t* sock = clib_get_sock_by_id(&l4_satck, sockid);

    return clib_getpeername(sock, sockid, addr, addrlen);
}

inline ssize_t
clib_bsd_read(i32_t sockid, char *buf, size_t len)
{
    clib_sock_t* sock = clib_get_sock_by_id(&l4_satck, sockid);

    return clib_read(sock, sockid, buf, len);
}

// ssize_t
// clib_bsd_recv(i32_t sockid, char *buf, size_t len, i32_t flags);

ssize_t
clib_bsd_write(i32_t sockid, const char *buf, size_t len) 
{
    clib_sock_t* sock = clib_get_sock_by_id(&l4_satck, sockid);

    return clib_write(sock, sockid, buf, len);
}